package com.ckjava.service.base;

import com.ckjava.aop.annotation.MultiDataSource;
import com.ckjava.dao.base.BaseMyBatisDao;
import com.ckjava.entity.base.BaseMybatisEntity;
import com.ckjava.entity.base.PageParamer;
import com.ckjava.xutils.Constants;
import com.ckjava.xutils.JsonUtils;
import com.ckjava.xutils.http.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Transactional(readOnly = true)
public abstract class BaseMybatisCrudService<E extends BaseMybatisEntity, D extends BaseMyBatisDao<E>> implements Constants {

    private static Logger logger = LoggerFactory.getLogger(BaseMybatisCrudService.class);

    @Autowired
    protected D dao;

    /**
     * 获取子类的 Class 类型
     * @return
     */
    public abstract Class<E> getClassType();

    /**
     * 根据主键 id 获取
     * @param id
     * @return
     */
    public Optional<E> get(long id) {
        return Optional.ofNullable(dao.get(id));
    }

    /**
     * 根据主键 id 获取
     * @return
     */
    public Optional<List<E>> getAll() {
        return Optional.ofNullable(dao.getAll());
    }

    /**
     * 根据参数获取数据列表
     *
     * @param entity
     * @return
     */
    public Optional<List<E>> getByParam(E entity) {
        return Optional.ofNullable(dao.getByParam(entity));
    }

    /**
     * 分页获取列表
     * @param pageParamer
     * @return
     */
    public Optional<Page<E>> getPage(PageParamer pageParamer) {
        Map<String, String> conditionMap = pageParamer.getSearch().getPredicateObject();
        if (conditionMap == null) {
            conditionMap = new HashMap<>();
        }
        String jsonString = JsonUtils.toJSONString(conditionMap);

        E entity = JsonUtils.readJavaObject(jsonString, getClassType()).orElse(null);
        entity.setPageParamer(pageParamer);

        return Optional.ofNullable(new Page<E>(pageParamer.getPagination().getStart(), pageParamer.getPagination().getNumber(), dao.getCount(entity), dao.getPage(entity)));
    }

    /**
     * 保存
     * @param entity
     * @return
     */
    @Transactional
    public Optional<Long> save(E entity) {
        if (entity.getCreateDate() == null) {
            entity.setCreateDate(new Date());
        }
        dao.save(entity);
        return Optional.ofNullable(entity.getId());
    }

    /**
     * 修改
     * @param entity
     * @return
     */
    @Transactional
    public Optional<Long> update(E entity) {
        if (entity.getUpdateDate() == null) {
            entity.setUpdateDate(new Date());
        }
        dao.update(entity);
        return Optional.ofNullable(entity.getId());
    }

    @Transactional
    public Optional<Long> saveOrUpdate(E entity) {
        if (entity.getId() == null) {
            return save(entity);
        } else {
            return update(entity);
        }
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Transactional
    public Optional<Integer> delete(Long id) {
        return Optional.ofNullable(dao.delete(id));
    }

    /**
     * 物理删除
     * @param id
     * @return
     */
    @Transactional
    public Optional<Integer> deletePhysical(Long id) {
        return Optional.ofNullable(dao.deletePhysical(id));
    }

}
